
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Kafka中的消息是怎么存储的？ - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Kafka中的消息是怎么存储的？ - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">Kafka中的分区（Partition）是什么？它在消息存储中扮演什么角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">分区是Kafka中主题（Topic）的逻辑存储单元，每个主题可以被划分为一个或多个分区。每个分区都是一个有序的、不可变的消息日志，新的消息总是被追加到日志的末尾，这种设计保证了消息的顺序性和持久性。</div>
          </div>
          <div class="card-source">来源: 分区</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">什么是消息偏移量（Offset），它在Kafka中有什么用途？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">每条消息在分区中都有一个唯一的、从零开始递增的偏移量，用于标识其在分区中的位置。消费者通过跟踪和提交偏移量来记录自己的消费进度，以便在重启或重新平衡后能从上次停止的位置继续消费。</div>
          </div>
          <div class="card-source">来源: 偏移量</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">Kafka是如何实现消息的持久化存储的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka的消息被持久化存储在磁盘上的日志文件（也称为日志段）中。消息以追加的方式写入文件末尾，确保了即使在系统发生故障或重启后，消息仍然可以被恢复和重新处理。</div>
          </div>
          <div class="card-source">来源: 消息的持久化</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">Kafka为什么要将消息日志划分为日志段（Log Segment）？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka将消息日志划分为多个日志段，主要是为了控制日志文件的大小并提高存储效率。当一个日志段达到预设的大小限制时，系统会关闭当前段并创建一个新段。这种机制还有利于实施日志保留策略，例如删除旧的日志段以释放磁盘空间。</div>
          </div>
          <div class="card-source">来源: 日志段的划分</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">架构</div>
          <div class="card-question">在Kafka的分区模型中，领导者（Leader）和副本（Replica）的角色是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">架构</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">每个分区都有一个领导者（Leader）和零个或多个副本（Replica）。分区的领导者负责处理该分区所有的读写请求，而副本则从领导者同步数据，用于提供容错性和高可用性。</div>
          </div>
          <div class="card-source">来源: 分区</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Kafka如何利用索引文件实现高效的消息检索？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">每个分区的消息日志都配有对应的索引文件，该文件存储了消息偏移量与其在磁盘上物理文件位置的映射关系。借助索引，Kafka可以快速地根据指定的偏移量定位并读取消息，从而支持高效的跳跃式读取操作。</div>
          </div>
          <div class="card-source">来源: 索引</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">Kafka的日志保留策略（Log Retention Policy）是如何工作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka允许根据时间或大小来配置消息的保留策略。当消息日志超过了配置的保留期限（如7天）或大小限制时，Kafka会自动删除旧的日志段，从而有效管理磁盘空间。</div>
          </div>
          <div class="card-source">来源: 消息日志</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">什么是消费者重新平衡（Consumer Rebalance），在此过程中消费进度是如何保证的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当消费者组内的消费者数量发生变化时，会触发重新平衡操作，重新为消费者分配分区。由于消费者会定期提交其消费的偏移量给Kafka集群，这些位移信息被持久化保存，因此即使分区被重新分配，消费者也能在新分配的分区上从上次记录的偏移量继续消费。</div>
          </div>
          <div class="card-source">来源: 偏移量</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">“追加写入”（Append-only）是Kafka日志设计的核心原则，它带来了哪些主要优点？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">“追加写入”指新的消息总是被添加到日志文件的末尾。这种方式主要有两个优点：一是保证了分区内消息的顺序性；二是提供了非常高的写入性能，因为顺序写磁盘的效率远高于随机写。</div>
          </div>
          <div class="card-source">来源: 消息日志</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
